package com.sanqi.common.utils;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.function.BiConsumer;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;

/**
 * @ClassName SQBeanUtil
 * @Description
 * @author duany
 * @Date 2022-11-16 15:13:22
 * @version 1.0.0
 */
public class SQBeanUtil {
    public static <T, K> void setFieldValue(T bean, BiConsumer<T, K> consumer, K value) {
        if(null == bean) {
            return;
        }
        consumer.accept(bean, value);
    }
    
    /**
     * 根据泛型创建java对象,并赋值id和createTime
     * @param <T>
     * @param clazz
     * @return
     */
    public static <T> T createNewBean(Class<T> clazz) {
        T t = null;
        try {
            t = clazz.getDeclaredConstructor().newInstance();
            Field idField = clazz.getDeclaredField("id");
            if(null != idField) {
                idField.setAccessible(true);
                idField.set(t, IdUtil.getSnowflake(0, 0).nextIdStr());
                idField.setAccessible(false);
            }
            Field timeField = clazz.getDeclaredField("createTime");
            if(null != timeField) {
                timeField.setAccessible(true);
                timeField.set(t, DateUtil.date());
                timeField.setAccessible(false);
            }
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (SecurityException e) {
            e.printStackTrace();
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
        
        return t;
    }

    /**
     * @Description
     * @param <T>
     * @param t
     * @return
     * Create at: 2022-11-16 15:13:42
     * @author: duany
     * Revision:
     *    2022-11-16 15:13:42 - first revision by duany
     *
     */
    public static <T> T setTextListEmpty(T t) {
        synchronized (SQBeanUtil.class) {
            Class<? extends Object> clazz = t.getClass();
            Field[] declaredFields = clazz.getDeclaredFields();
            if(null != declaredFields) {
                for (int i = 0; i < declaredFields.length; i++) {
                    Field field = declaredFields[i];
                    try {
                        if (field.getType().isAssignableFrom(List.class)) {
                            field.setAccessible(true);
                            Object object = field.get(t);
                            if(null == object) {
                                field.set(t, Collections.emptyList());
                            }
                            field.setAccessible(false);
                        }
                        if (field.getType().isAssignableFrom(String.class)) {
                            field.setAccessible(true);
                            Object object = field.get(t);
                            if(null == object) {
                                field.set(t, StrUtil.EMPTY);
                            }
                            field.setAccessible(false);
                        }
                    } catch (IllegalArgumentException e) {
                        e.printStackTrace();
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    }
                }
            }
            return t;
        }
    }

    /**
     * @Description
     * @param <T>
     * @param t
     * @param num
     * @return
     * Create at: 2022-11-16 15:13:51
     * @author: duany
     * Revision:
     *    2022-11-16 15:13:51 - first revision by duany
     *
     */
    public static <T> T  setDecimalScale(T t, int num) {
        synchronized(SQBeanUtil.class) {
            if(null != t) {
                Class<? extends Object> clazz = t.getClass();
                Field[] declaredFields = clazz.getDeclaredFields();
                if(null != declaredFields) {
                    for (int i = 0; i < declaredFields.length; i++) {
                        Field field = declaredFields[i];
                        try {
                            if (field.getType().isAssignableFrom(BigDecimal.class)) {
                                field.setAccessible(true);
                                Object object = field.get(t);
                                if(null == object) {
                                    field.set(t, BigDecimal.ZERO.setScale(num));
                                } else {
                                    field.set(t, ((BigDecimal)object).setScale(num));
                                }
                                field.setAccessible(false);
                            }
                        } catch (IllegalArgumentException e) {
                            e.printStackTrace();
                        } catch (IllegalAccessException e) {
                            e.printStackTrace();
                        }
                    }
                }

            }
        }

        return t;
    }

    /**
     * @Description
     * @param <T>
     * @param clazz
     * @return
     * Create at: 2022-11-16 15:13:59
     * @author: duany
     * Revision:
     *    2022-11-16 15:13:59 - first revision by duany
     *
     */
    public static <T> T createTextListEmptyBean(Class<T> clazz) {
        synchronized (SQBeanUtil.class) {
            T t = null;
            try {
                t = clazz.getDeclaredConstructor().newInstance();
                Field[] declaredFields = clazz.getDeclaredFields();
                if(null != declaredFields) {
                    for (int i = 0; i < declaredFields.length; i++) {
                        Field field = declaredFields[i];
                        if (field.getType().isAssignableFrom(List.class)) {
                            field.setAccessible(true);
                            field.set(t, Collections.emptyList());
                            field.setAccessible(false);
                        }
                        if (field.getType().isAssignableFrom(String.class)) {
                            field.setAccessible(true);
                            field.set(t, StrUtil.EMPTY);
                            field.setAccessible(false);
                        }
                    }
                }

            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (IllegalArgumentException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            } catch (SecurityException e) {
                e.printStackTrace();
            }

            return t;
        }
    }
    
    /**
     * 获取类的所有属性，包括父类
     * 
     * @param object
     * @return
     */
    public static Field[] getAllFields(Object object) {
        Class<?> clazz = object.getClass();
        List<Field> fieldList = CollUtil.newArrayList();
        while (clazz != null) {
            fieldList.addAll(new ArrayList<>(Arrays.asList(clazz.getDeclaredFields())));
            clazz = clazz.getSuperclass();
        }
        Field[] fields = new Field[fieldList.size()];
        fieldList.toArray(fields);
        return fields;
    }
    
    public static <T> T setBeanStringEmptyToNull(T t) {
        Class<? extends Object> clazz = t.getClass();
        Field[] declaredFields = clazz.getDeclaredFields();
        if(null != declaredFields) {
            for (int i = 0; i < declaredFields.length; i++) {
                Field field = declaredFields[i];
                try {
                    if (field.getType().isAssignableFrom(String.class)) {
                        field.setAccessible(true);
                        String object = (String)field.get(t);
                        if(StrUtil.isBlank(object)) {
                            field.set(t, null);
                        }
                        field.setAccessible(false);
                    }
                } catch (IllegalArgumentException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        }
        
        return t;
    }

}
